# -*- coding: utf-8 -*-

import os
import stat
import time
from PySide2.QtCore import QObject, Signal, QCoreApplication
from utils.ssh_client import SSHClient

class UploadWorker(QObject):
    progress = Signal(int, int)  # value, thread_index
    log = Signal(str, int)  # message, thread_index
    finished = Signal(int)  # thread_index
    
    def __init__(self, files, connection, upload_dir="/tmp", thread_index=0):
        super().__init__()
        self.files = files
        self.connection = connection
        self.upload_dir = upload_dir
        self.thread_index = thread_index
        self.ssh_client = None
        
    def run(self):
        """执行上传任务"""
        try:
            # 连接SSH
            self.ssh_client = SSHClient(
                host=self.connection["host"],
                port=self.connection["port"],
                username=self.connection["username"],
                password=self.connection["password"]
            )
            self.ssh_client.connect()
            # 添加连接标识，确保并发时日志清晰
            connection_id = self.connection.get('thread_index', 0)
            connection_unique_id = self.connection.get('connection_id', f"upload_{connection_id}")
            self.log.emit(f"[{connection_unique_id}] 已连接到 {self.connection['host']}", self.thread_index)
            
            # 上传文件和目录
            total_items = len(self.files)
            for i, item_path in enumerate(self.files):
                if os.path.isfile(item_path):
                    # 上传单个文件
                    filename = os.path.basename(item_path)
                    self.log.emit(f"正在上传文件 {filename} 到 {self.connection['host']}", self.thread_index)
                    
                    # 执行上传到指定目录（确保使用Linux路径分隔符）
                    remote_path = os.path.join(self.upload_dir, filename).replace("\\", "/")
                    self.ssh_client.upload_file(item_path, remote_path)
                    
                    self.log.emit(f"上传完成 {filename}", self.thread_index)
                elif os.path.isdir(item_path):
                    # 上传整个目录
                    dirname = os.path.basename(item_path)
                    self.log.emit(f"正在上传目录 {dirname} 到 {self.connection['host']}", self.thread_index)
                    
                    # 创建远程目录
                    remote_dir = os.path.join(self.upload_dir, dirname).replace("\\", "/")
                    self._create_remote_dir(remote_dir)
                    
                    # 递归上传目录内容
                    self._upload_directory(item_path, remote_dir)
                    
                    self.log.emit(f"上传完成目录 {dirname}", self.thread_index)
                else:
                    self.log.emit(f"路径不存在: {item_path}", self.thread_index)
                
                # 更新进度
                progress_value = int((i + 1) / total_items * 100)
                self.progress.emit(progress_value, self.thread_index)
                
                # 处理事件队列，确保信号能够及时发送
                QCoreApplication.processEvents()
                    
            self.log.emit(f"所有文件和目录上传完成到 {self.connection['host']}:{self.upload_dir}", self.thread_index)
        except Exception as e:
            self.log.emit(f"上传失败: {str(e)}", self.thread_index)
        finally:
            if self.ssh_client:
                self.ssh_client.close()
            self.finished.emit(self.thread_index)
            
    def _create_remote_dir(self, remote_dir):
        """创建远程目录（递归创建）"""
        try:
            # 分割路径并逐级创建
            dirs = remote_dir.strip("/").split("/")
            current_path = ""
            for dir_name in dirs:
                if current_path:
                    current_path = f"{current_path}/{dir_name}"
                else:
                    current_path = dir_name
                full_path = f"/{current_path}"
                
                try:
                    # 尝试进入目录，如果失败则创建
                    self.ssh_client.sftp.chdir(full_path)
                except:
                    # 目录不存在，创建它
                    try:
                        self.ssh_client.sftp.mkdir(full_path)
                    except:
                        pass  # 目录可能已存在
        except Exception as e:
            self.log.emit(f"创建远程目录失败 {remote_dir}: {str(e)}")
            
    def _upload_directory(self, local_dir, remote_dir):
        """递归上传目录"""
        try:
            # 遍历本地目录
            for item in os.listdir(local_dir):
                local_path = os.path.join(local_dir, item)
                # 确保使用Linux路径分隔符处理远程路径
                remote_path = os.path.join(remote_dir, item).replace("\\", "/")
                
                if os.path.isfile(local_path):
                    # 上传文件
                    self.log.emit(f"正在上传文件 {item}", self.thread_index)
                    self.ssh_client.upload_file(local_path, remote_path)
                elif os.path.isdir(local_path):
                    # 创建远程子目录并递归上传
                    self._create_remote_dir(remote_path)
                    self._upload_directory(local_path, remote_path)
        except Exception as e:
            self.log.emit(f"上传目录 {local_dir} 失败: {str(e)}", self.thread_index)

class DownloadWorker(QObject):
    progress = Signal(int, int)  # value, thread_index
    log = Signal(str, int)  # message, thread_index
    finished = Signal(int)  # thread_index
    start = Signal(int)  # thread_index
    
    def __init__(self, files, directory, connection, create_connection_dir=False, thread_index=0):
        super().__init__()
        self.files = files
        self.directory = directory
        self.connection = connection
        self.create_connection_dir = create_connection_dir
        self.thread_index = thread_index
        self.ssh_client = None
        
    def run(self):
        """执行下载任务"""
        # 发射开始信号
        self.start.emit(self.thread_index)
        
        try:
            # 连接SSH
            self.ssh_client = SSHClient(
                host=self.connection["host"],
                port=self.connection["port"],
                username=self.connection["username"],
                password=self.connection["password"]
            )
            self.ssh_client.connect()
            # 添加连接标识，确保并发时日志清晰
            connection_id = self.connection.get('thread_index', 0)
            connection_unique_id = self.connection.get('connection_id', f"download_{connection_id}")
            self.log.emit(f"[{connection_unique_id}] 已连接到 {self.connection['host']}", self.thread_index)
            
            # 如果需要为每个连接创建独立目录，则构建连接目录路径（仅使用连接名作为目录名）
            if self.create_connection_dir:
                connection_dir_name = self.connection['name']
                # 使用Windows路径分隔符处理本地路径
                download_directory = os.path.join(self.directory, connection_dir_name)
                # 确保连接目录存在
                if not os.path.exists(download_directory):
                    os.makedirs(download_directory)
            else:
                # 使用Windows路径分隔符处理本地路径
                download_directory = self.directory
            
            # 下载文件
            total_files = len(self.files)
            for i, remote_path in enumerate(self.files):
                # 从远程路径获取文件名（确保使用Linux路径分隔符）
                filename = os.path.basename(remote_path.replace("\\", "/"))
                # 使用Windows路径分隔符处理本地路径
                local_path = os.path.join(download_directory, filename)
                
                # 确保本地目录存在（使用Windows路径分隔符）
                local_dir = os.path.dirname(local_path)
                if not os.path.exists(local_dir):
                    os.makedirs(local_dir)
                
                self.log.emit(f"正在下载 {filename} from {self.connection['host']}", self.thread_index)
                
                try:
                    # 检查远程路径是文件还是目录
                    file_stat = self.ssh_client.sftp.stat(remote_path)
                    if stat.S_ISDIR(file_stat.st_mode):
                        # 如果是目录，递归下载目录内容
                        self.download_directory(remote_path, local_path)
                    else:
                        # 如果是文件，直接下载
                        self.ssh_client.download_file(remote_path, local_path)
                except Exception as e:
                    self.log.emit(f"下载 {remote_path} 失败: {str(e)}", self.thread_index)
                    continue
                
                # 更新进度
                progress_value = int((i + 1) / total_files * 100)
                self.progress.emit(progress_value, self.thread_index)
                
                # 处理事件队列，确保信号能够及时发送
                QCoreApplication.processEvents()
                
                self.log.emit(f"下载完成 {filename}", self.thread_index)
                
            self.log.emit(f"所有文件下载完成从 {self.connection['host']} 到 {download_directory}", self.thread_index)
        except Exception as e:
            self.log.emit(f"下载失败: {str(e)}", self.thread_index)
        finally:
            if self.ssh_client:
                self.ssh_client.close()
            # 添加一个小延迟确保所有信号都被处理
            QCoreApplication.processEvents()
            time.sleep(0.1)
            self.finished.emit(self.thread_index)
            
    def download_directory(self, remote_dir, local_dir):
        """递归下载目录"""
        try:
            # 创建本地目录（使用Windows路径分隔符）
            if not os.path.exists(local_dir):
                os.makedirs(local_dir)
                
            # 获取远程目录内容
            items = self.ssh_client.sftp.listdir_attr(remote_dir)
            
            for item in items:
                # 确保使用Linux路径分隔符处理远程路径
                remote_path = os.path.join(remote_dir, item.filename).replace("\\", "/")
                # 使用Windows路径分隔符处理本地路径
                local_path = os.path.join(local_dir, item.filename)
                
                if stat.S_ISDIR(item.st_mode):
                    # 递归下载子目录
                    self.download_directory(remote_path, local_path)
                else:
                    # 下载文件（逐文件记录日志）
                    self.log.emit(f"正在下载 {remote_path} from {self.connection['host']}", self.thread_index)
                    self.ssh_client.download_file(remote_path, local_path)
                    self.log.emit(f"下载完成 {remote_path}", self.thread_index)
                    
                # 处理事件队列，确保信号能够及时发送
                QCoreApplication.processEvents()
                    
        except Exception as e:
            self.log.emit(f"下载目录 {remote_dir} 失败: {str(e)}", self.thread_index)